/*
 * RefCount.cpp
 *
 *  Created on: Nov 10, 2008
 *      Author: brain
 */

#include "AlphaExpansion.h"



AlphaExpansion::AlphaExpansion(Energy &energy,CVImage *image,vector<int> *labels):nbrs(1)
{

	_energy=&energy;
	labelling=new CVImage(cvCreateImage(cvSize(image->width(),image->height()),IPL_DEPTH_32S, 1));
	labelling->clear((*labels)[0]);
	current_iteration=1;
	_labels=labels;
	graph=new GraphType(labelling->height() * labelling->width(), labelling->height() * labelling->width()*4,NULL);

}
int auxs(char a)
{
	if (a>0)
		return a;
	return 0;
}
uint AlphaExpansion::IndeX(uint x,uint y)
{
	return labelling->width()*y+x;
}
void AlphaExpansion::Labeled2Graph(int label)
{

	uint i,j,n,index=0;
	for (j=0;j<labelling->height();j++)
		for (i=0;i<labelling->width();i++)
		{
			graph->add_node();
			if(labelling->Pixel(i,j,0)==label)
				graph->add_tweights( index,   /* capacities */  _energy->DataEnergy(i,j,label), INFINITE_D );
			else
				graph->add_tweights( index,   /* capacities */  _energy->DataEnergy(i,j,label),_energy->DataEnergy(i,j,labelling->Pixel(i,j,0)));
			index++;
		}
	for (n=0;n<nbrs.GetLength();n++)
	{
		for (i=auxs(-nbrs.iterx(n)) ; i<labelling->width()-auxs(nbrs.iterx(n)) ;i++)
			for (j=auxs(-nbrs.itery(n));j<labelling->height()-auxs(nbrs.itery(n)) ;j++)
			{
				if( labelling->Pixel(i,j,0)==labelling->Pixel(i+nbrs.iterx(n),j+nbrs.itery(n),0))
				{
					graph->add_edge(IndeX(i,j),IndeX(i+nbrs.iterx(n),j+nbrs.itery(n)),_energy->SmoothEnergy(labelling->Pixel(i,j,0),label),_energy->SmoothEnergy(labelling->Pixel(i,j,0),label));
				}
				else
				{
					graph->add_node();
					graph->add_tweights( index,   /* capacities */  0, _energy->SmoothEnergy(labelling->Pixel(i,j,0),labelling->Pixel(i+nbrs.iterx(n),j+nbrs.itery(n),0) ));
					graph->add_edge(IndeX(i,j),index,_energy->SmoothEnergy(labelling->Pixel(i,j,0),label),_energy->SmoothEnergy(labelling->Pixel(i,j,0),label));
					//graph->Connect(IndeX(i,j),index,SmoothEnergy(i,j,label));
					graph->add_edge(IndeX(i+nbrs.iterx(n),j+nbrs.itery(n)),index,_energy->SmoothEnergy(labelling->Pixel(i+nbrs.iterx(n),j+nbrs.itery(n),0),label),_energy->SmoothEnergy(labelling->Pixel(i+nbrs.iterx(n),j+nbrs.itery(n),0),label));
					//graph->Connect(IndeX(i+nbrs.iterx(n),j+nbrs.itery(n)),index,SmoothEnergy(i+nbrs.iterx(n),j+nbrs.itery(n),label));
					//graph->Connect(auxiliary,graph->VertexIndex(sink),SmoothEnergy(i,j,i+nbrs.iterx(n),j+nbrs.itery(n)));
					index++;
				}
			}
	}
}
AlphaExpansion::~AlphaExpansion()
{
	delete graph;
	delete labelling;
}

CVImage *AlphaExpansion::next_iteration()
{
	if (current_iteration==_labels->size())
	{
		return labelling;
	}

	Labeled2Graph((*_labels)[current_iteration]);
	GenerateLabelling((*_labels)[current_iteration]);
	current_iteration++;
	graph->reset();
	return labelling;
}

void AlphaExpansion::GenerateLabelling(int label)
{
	graph->maxflow(false,NULL);

	int *intensity;
	uint i;
	for (i=0;i< labelling->height() * labelling->width();i++)
	{
		if (graph->what_segment(i) == GraphType::SINK)
		{
			intensity=(int*)labelling->Pix(i,0);
			*intensity=label;
		}
	}
}

bool AlphaExpansion::iscomplete()
{
	if (current_iteration==_labels->size())
		return true;
	return false;
}

